#include <iostream>
#include <fstream>
#include <sstream>
#include <pthread.h>
#include <map>
#include <string>
#include <utility>
#include <chrono>

using std::pair;
using std::map;
using std::ifstream;
using std::ofstream;
using std::istringstream;
using std::ostringstream;
using std::string;
using std::cout;
using std::cin;
using std::endl;

//恶汉式的单例模式
class Dir {
public://公有函数
    // 初始化instance
    static Dir* getInstance() {
        if (ms_instance == nullptr) {
            pthread_once(&ms_once, routine);
        }
        return ms_instance;
    }
    //将<<和>>友元
    friend ofstream& operator<<(ofstream& ofs, const Dir& rhs);
    friend ifstream& operator>>(ifstream& ifs, Dir& rhs);
private://私有的成员函数
    //删除拷贝构造和赋值运算符
    Dir(const Dir&) = delete;
    Dir& operator=(const Dir&) = delete;
    //构造函数
    Dir()
    {
        cout << "Dir()" << endl;
    }
    //析构函数
    ~Dir() {
        cout << "~Dir()" << endl;
    }
    //routine
    static void routine() {
        ms_instance = new Dir{};
        atexit(destroyInstance);
    }
    static void destroyInstance() {
        if (ms_instance) {
            delete ms_instance;
            ms_instance = nullptr;
            cout << "release over" << endl;
        }
    }
    //判断字符是否是字母
    static bool is_char(const char ch) {
        return(ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
    }
    //更新word，删除无效的字符
    static string& update_word(string& word) {
        auto it = word.begin();
        while (it < word.end()) {
            //不为字母的字符擦除
            if (is_char(*it) == 0) {
                it = word.erase(it);
                continue;
            }
            it++;
        }
        return word;
    }
    //将非空的word插入字典
    static int push_word(const string& word) {
        //不为空的word才插入
        if (word.size()) {
            getInstance()->m_dir[word]++;
        }

        return 0;
    }
private://私有数据成员
    map<string, size_t> m_dir;
    static pthread_once_t ms_once;
    static Dir* ms_instance;
};//end of class Dir
//静态成员初始化(动态饿汉)
pthread_once_t Dir::ms_once = PTHREAD_ONCE_INIT;
Dir* Dir::ms_instance = getInstance();

//重载<<和>>
ofstream& operator<<(ofstream& ofs, const Dir& rhs) {

    for (auto& element : Dir::getInstance()->m_dir) {
        ostringstream oss;
        oss << element.first << " : " << element.second << endl;
        ofs << oss.str();
    }
    return ofs;
}
ifstream& operator>>(ifstream& ifs, Dir& rhs) {
    if (!ifs) {
        cout << "this is a bid ifstream" << endl;
    }
    //读一行
    string line;
    while (std::getline(ifs, line)) {
        //绑定一行到字符串输入流
        string word;
        istringstream iss(line);
        //不用担心前一个word影响当前word>>运算符重载时会清空并覆盖
        while (iss >> word) {
            // cout << word << endl;
            //更新word，删除无效的字符
            Dir::update_word(word);
            // cout << word << endl;
            //将非空的word插入字典
            Dir::push_word(word);
        }
    }
    return ifs;
}

void test() {
    ifstream ifs("The_Holy_Bible.txt");
    if (!ifs) {
        cout << "do not hava this file" << endl;
    }
    //读文件到dir
    ifs >> *Dir::getInstance();
    //写文件到外部文件
    ofstream ofs("Holy.txt");
    ofs << *Dir::getInstance();
}
int main() {
    // 记录开始时间点
    auto start = std::chrono::high_resolution_clock::now();
    // time_t start = time(NULL);
    test();
    // 记录结束时间点
    auto end = std::chrono::high_resolution_clock::now();
    // 计算时间差，并将其转换为毫秒
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();

    std::cout << "The operation took " << duration << " milliseconds." << std::endl;
    // time_t end = time(NULL);
    // cout << end - start << endl;
    return 0;
}